package pt.ist.meic.pava.JVSTMSync;


import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.aspectj.lang.reflect.FieldSignature;
import pt.ist.meic.pava.SyncCommons.*;
import jvstm.Transaction;
import jvstm.VBox;




/**
 * 
 * @author Antonio Massingue
 * @author Joao Matos
 * @author Nuno Santos
 * 
 * This aspect implements Software Transaction Memory in
 * 	the programmer classes.
 */
public aspect JVSTMSync {



	private boolean finished = true;

	
	
	private ConcurrentHashMap<String, VBox<Object>> boxes = 
		new ConcurrentHashMap<String, VBox<Object>>();
	
	
	
	
	
	/**
	 * Any method call marked as Atomic
	 */
//	pointcut withAtomic(): 
//		call(@Atomic * *.*(..)) && !cflowbelow(call(@Atomic * *.*(..)));
	
	
	
	/**
	 * Before this method is executed
	 * begin the Transaction
	 */
/*	before(): withAtomic() {

		Transaction.begin();
		this.finished = false;
		
	}*/
	
	/**
	 * After the method is executed
	 * commit the transaction or
	 * abort
	 */
/*	after(): withAtomic() {
		
		try {
			Transaction.commit();
			this.finished = true;
		}
		catch(jvstm.CommitException cme) {
<<<<<<< .mine
			System.out.println("banhada");
=======
			System.out.println("Aborted");
>>>>>>> .r107
			Transaction.abort();
			this.finished = true;
			
		}
		finally {
			if(! finished){
				System.out.println("Aborted");
				Transaction.abort();
			}
		}
	}
	

	
	
	*/
	
	
	
	/**
	 * Within any class marked as Shared
	 */
	pointcut fieldChange():
		set(* *.*) && within(@Shared *);
	
	before(Object o): fieldChange() && args(o){

		try {
			
			FieldSignature sig = (FieldSignature)thisJoinPoint.getSignature();
			
			Field field = sig.getField();
			
			field.setAccessible(true);/*In case the field is private*/
			
			if(!this.boxes.containsKey(field.toString())) {/*Is it a new field?*/
				
				VBox<Object> newVBox = new VBox<Object>();
				newVBox.put(o);

				this.boxes.put(field.toString(),newVBox);
				
			}
			else {/*No.. it is an update to an existing field*/
	
				this.boxes.get(field.toString()).put(o);/*update vbox*/
			}
		
		} 
		catch (IllegalArgumentException e) {/*Do nothing?*/}
		
	}

	
	
	
	
	
	
	
	pointcut fieldRead():
		get(* *.*) && within(@Shared *);
	
	Object around() : fieldRead(){
		
		FieldSignature sig = (FieldSignature)thisJoinPoint.getSignature();
		
		Field field = sig.getField();
		
		if(this.boxes.containsKey(field.toString())){
			return this.boxes.get(field.toString()).get();
		}
		else{
			return proceed();
		}

		
	}
	
	
	/*private VBox<Object> isMe(FieldSignature b){
		
		for(VBox<Object> a : this.boxes.values()){
			
			
			
		}
		
	}*/
	
	
	
	
	
	
	
	
	
	
	
	
	
}
